using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Services;
using MainGame.StateManagement;
using MainGame.SaveData;

namespace MainGame.GamePlay
{
  /// <summary>
  /// Gestiamo le regole di gioco, l'inizio della partita,
  /// le condizioni di fine partita e gli assegnamenti di punteggio
  /// </summary>
  public class GamePlayLayer : PlayerLayer
  {
    public GamePlayLayer(Game game)
      : base(game)
    {
      UpdateOrder = (int)ComponentOrders.LOGIC;
    }

    protected override void OnTurnChanged()
    {
      if (blocks.Count == NUM_PLAYERS)
      {
        if (blocks.All(b => b.Cards.Any()))
        {
          var reference_color = blocks[0].Cards.First().Color;
          var loser = blocks.Where(b => b.Cards.First().Color == reference_color)
                            .MaxBy(b => b.Cards.First().Value);
          //loser.PlayedBy.Score += NUM_PLAYERS;
          blocks.Clear();
        }
      }

      base.OnTurnChanged();
    }

    protected override void BoardManager_ClickPlayerCard(int player_index, int card_index)
    {
      base.BoardManager_ClickPlayerCard(player_index, card_index);
    }

    protected override void BoardManager_ReleasePlayerCard(int player_index, int card_index, bool sx)
    {
      // Game logic: checks between adjacent cards and removal of a card
      //Card a;
      //if (card_index > 0 && card_index < players[player_index].Cards.Count - 1)
      //{
      //  if (sx)
      //    a = players[player_index].Cards[card_index

      //}




      Card prevCard, nextCard;
      if (card_index > 0 && card_index < (players[player_index].Cards.Count() - 1))
      {
        int prevCardIdx = card_index - 1;
        int nextCardIdx = card_index + 1;
        prevCard = players[player_index].Cards[prevCardIdx];
        nextCard = players[player_index].Cards[nextCardIdx];
        if (players[player_index].CheckCards(prevCard, nextCard))
        {
          //++players[player_index].Score;
          //players[player_index].Cards[card_index].Selected = false;

          //players[player_index].Cards.RemoveAt(card_index);
          if (sx)
            players[player_index].Cards.RemoveAt(prevCardIdx);
          else
            players[player_index].Cards.RemoveAt(nextCardIdx);
        }
      }

      // Check if the victory/loss conditions are met
      CheckVictory(player_index);

      base.BoardManager_ReleasePlayerCard(player_index, card_index, sx);
    }

    protected override void StartGame()
    {
      //Difficulty
      int MaxValueCard = 13;
      if (Game.GetContext().currentConfig.difficulty == GameDifficulty.Easy) { MaxValueCard = 10; }
      //if (Game.GetContext().currentConfig.difficulty == GameDifficulty.Normal) { MaxValueCard = 13; }
      //if (Game.GetContext().currentConfig.difficulty == GameDifficulty.Hard) { MaxValueCard = 13; }

      var range = (from i in Enumerable.Range(1, MaxValueCard) select i);
      Func<CardColor, IEnumerable<Card>> colors = c =>
        from i in range select new Card() { Color = c, Value = i, Selected = false };

      // Crea un nuovo mazzo
      pack = new GamePlay.Pack()
      {
        Cards = colors(CardColor.Blue).Concat(
             colors(CardColor.Green)).Concat(
             colors(CardColor.Red)).Concat(
             colors(CardColor.White)).ToList()
      };

      // Definisce tipo di Mazzo (Semi delle Carte)
      for (int i = 0; i < pack.Cards.Count; i++)
      {
        // Difficulty
        //if (Game.GetContext().currentConfig.difficulty == GameDifficulty.Easy)
        //{ 
        //  if (pack.Cards.ElementAt(i).Color == CardColor.Green) pack.Cards.ElementAt(i).Color = CardColor.Red;
        //  if (pack.Cards.ElementAt(i).Color == CardColor.White) pack.Cards.ElementAt(i).Color = CardColor.Blue; 
        //}
        
        if (pack.Cards.ElementAt(i).Color == CardColor.Red) { pack.Cards.ElementAt(i).Seed = CardSeed.Hearts; }
        if (pack.Cards.ElementAt(i).Color == CardColor.Green) { pack.Cards.ElementAt(i).Seed = CardSeed.Diamonds; }
        if (pack.Cards.ElementAt(i).Color == CardColor.White) { pack.Cards.ElementAt(i).Seed = CardSeed.Clubs; }
        if (pack.Cards.ElementAt(i).Color == CardColor.Blue) { pack.Cards.ElementAt(i).Seed = CardSeed.Spades; }
      }

      // Mischia il mazzo
      var r = new Random();
      for (int j = 0; j < 3; ++j)
      {
        for (int i = 0; i < pack.Cards.Count / 2; i++)
        {
          var ai = r.Next(pack.Cards.Count);
          var bi = r.Next(pack.Cards.Count);

          var a = pack.Cards[ai];
          var b = pack.Cards[bi];

          pack.Cards[bi] = a;
          pack.Cards[ai] = b;
        }
      }

      // Crea i giocatori
      for (int p = 0; p < NUM_PLAYERS; p++)
        players.Add(new Player()
        {
          Score = 0,
          Hand = new PlayerBlock() { Cards = new List<Card>() },
          IsHuman = false,
          Name = Locale.Strings.Player + " " + p.ToString() //"Player " + p.ToString()
        });
#warning PER ATTIVARE UN GIOCATORE UMANO, VEDERE QUI
      players[0].IsHuman = true;
      players[0].Name = Game.GetContext().currentProfile.username;

      // Assegna le carte
      for (int i = 0; i < STARTING_CARDS; i++)
      {
        for (int p = 0; p < NUM_PLAYERS; p++)
        {
          pick_player(p);
        }
      }

      //CurrentPlayerIndex = r.Next(NUM_PLAYERS);
      CurrentPlayerIndex = 0;
    }

    protected override void LoadGame(SavedGame savedGame)
    {
      // Carica il mazzo
      pack = savedGame.pack;

      // Carica i giocatori - solitario: 1 giocatore
      players.Add(new Player()
      {
        Score = 0,
        Hand = savedGame.playerCards,
        IsHuman = true,
        Name = Game.GetContext().currentProfile.username
      });

      CurrentPlayerIndex = 0;
    }

    /// <summary>
    /// Assegna una carta a un giocatore
    /// </summary>
    /// <param name="index">L'indice del giocatore nell'array dei giocatori</param>
    void pick_player(int index)
    {
      if (pack.Cards.Count > 0)
      {
        players[index].Cards.Add(pack.Cards.First());
        pack.Cards = pack.Cards.Skip(1).ToList();
      }
    }
  }
}
